<template>
  <div ref="refBox" style="height: 100%;"></div>
</template>

<script lang="ts" setup>
import {onMounted, ref} from 'vue'
import json from "../../public/json/flare-2.json";
import {hierarchy, HierarchyPointLink, HierarchyPointNode, linkHorizontal, linkRadial, select, tree} from "d3";

const refBox = ref<HTMLElement | null>(null);

interface TreeDatum {
  name: string
  value?: number
  children?: this[]
}

type PointLinkDatum = HierarchyPointLink<TreeDatum>
type PointNodeDatum = HierarchyPointNode<TreeDatum>

interface MindPointNode extends PointNodeDatum {
  offsetX?: number
  offsetY?: number
  position?: number
}

onMounted(() => {
  const boxDmo = refBox.value
  if (boxDmo) {
    const {width, height} = boxDmo.getBoundingClientRect()

    let xAverage = 0
    let centerValue = 0

    let containerSelection = select<HTMLElement, null>(boxDmo).append('svg')
      .attr('width', width)
      .attr('height', height)
      .attr('style', 'user-select: none;')
      .attr('viewBox', `0 0 ${width} ${height}`)

    let boxSelection = containerSelection.append('g')
      .attr('transform', 'translate(1200, 600)')

    const root = hierarchy<TreeDatum>(json)

    const layoutRoot = tree<TreeDatum>().nodeSize([40, 14])(root)

    console.log(layoutRoot)

    const links = layoutRoot.links()
    const nodes = layoutRoot.descendants()

    if (layoutRoot.children) {
      const firstNode = layoutRoot.children[0]
      const lastNode = layoutRoot.children[layoutRoot.children.length - 1]
      centerValue = (lastNode.x + firstNode.x) / 2
      xAverage = (lastNode.x - firstNode.x) / 4
    }

    function getX(datum: MindPointNode) {

      if (datum.position) {
        return datum.y * datum.position
      }

      if (datum.depth <= 1) {
        datum.position = datum.x > centerValue ? -datum.y : datum.y
      } else {
        datum.position = (datum.parent as MindPointNode).position as number
      }

      return datum.y * datum.position
    }

    function getParentOffsetX(datum: MindPointNode | null): number {
      if (datum) {
        if (datum.depth > 1) {
          datum.offsetX = getParentOffsetX(datum.parent)
        }
        return datum.offsetX as number
      }
      return 0
    }

    function getY(datum: MindPointNode) {

      if (typeof datum.offsetX === "number") {
        return datum.x + datum.offsetX
      }

      if (datum.depth === 0) {
        datum.offsetX = 0
      } else if (datum.depth === 1) {
        datum.offsetX = xAverage * (datum.x > centerValue ? -1 : 1)
      } else {
        datum.offsetX = getParentOffsetX(datum.parent)
      }

      return datum.x + datum.offsetX
    }

    console.log(nodes, xAverage)

    const horizontal = linkHorizontal<unknown, PointLinkDatum, PointNodeDatum>().x(getX).y(getY)
    const radial = linkRadial<unknown, PointLinkDatum, PointNodeDatum>().angle(d => d.x).radius(d => d.y * 400)

    const pathSelection = boxSelection.selectAll('path')
    pathSelection.data(links, link => (link as PointLinkDatum).source.data.name)
      .enter()
      .append('path')
      .attr('d', d => horizontal(d))
      .attr('fill', 'transparent')
      .attr('stroke', '#000')

    boxSelection.selectAll('text')
      .data(nodes, d => (d as PointNodeDatum).data.name)
      .enter()
      .append('text')
      .text(d => d.data.name)
      // .attr("transform", d => `rotate(${d.x * 180 / Math.PI - 90}) translate(${d.y * 400},0)`)
      .attr('x', getX)
      .attr('y', getY)

  }

})
</script>

<style scoped lang="less">

</style>
